﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ParserGenerator.GrammarConstruction;

namespace ParserGenerator.ParserConstruction
{
    [Serializable]
    public sealed class ParserAutomatonActions : ReadOnlyDictionary<GrammarTerminalSymbol, ParserAutomatonAction>
    {
        public int Number => State.Number;
        public ParserAutomatonState State { get; }

        internal ParserAutomatonActions(ParserAutomatonState state, ParserAutomatonReductionLookaheadSets lookaheadSets)
            : base(new Dictionary<GrammarTerminalSymbol, ParserAutomatonAction>())
        {
            if (state == null)
                throw new ArgumentNullException(nameof(state));
            State = state;
            var tokens = state.GetShiftTokens();
            foreach (var t in state.Transitions)
            {
                if (t.Key.IsNonterminal)
                    continue;
                var token = t.Key.AsTerminal;
                var target = state.Transitions[token];
                var shift = new ParserAutomatonShift(state, token, target);
                var action = new ParserAutomatonAction(state, token);
                action.Add(shift);
                Dictionary.Add(token, action);
            }
            if (state.IsConsistent)
                return;
            foreach (var t in state.Reductions)
            {
                var lookaheadSet = lookaheadSets[t.Value.Production];
                foreach (var token in lookaheadSet)
                {
                    ParserAutomatonAction action;
                    if (!Dictionary.TryGetValue(token, out action))
                    {
                        action = new ParserAutomatonAction(state, token);
                        Dictionary.Add(token, action);
                    }
                    action.Add(t.Value);
                }
            }
        }
    }
}
